import utils
import re
import random
import json
import time
import requests
from login import OneClickLogin
from scan import Scan
from urllib3.exceptions import InsecureRequestWarning
# 禁用安全请求警告
requests.urllib3.disable_warnings(InsecureRequestWarning)
import datetime

today = datetime.date.today()  # 今天
yest = today - datetime.timedelta(days=1)
before_yest = today - datetime.timedelta(days=2)
before_yesterday = str(before_yest).replace('-', '')
yesterday = str(yest).replace('-', '')
# 昨天开始时间戳
yesterday_start_time = int(time.mktime(time.strptime(str(yest), '%Y-%m-%d')))

# 昨天结束时间戳
yesterday_end_time = int(time.mktime(time.strptime(str(today), '%Y-%m-%d'))) - 1

# 前天开始时间戳
before_yesterday_start_time = int(time.mktime(time.strptime(str(before_yest), '%Y-%m-%d')))

header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36",
    "X-Requested-With": "XMLHttpRequest"
}

class WeChatClient:
    def __init__(self, login_service, url='https://mp.weixin.qq.com'):
        """
        通过moka登录接口获取公众号后台资料
        :param OneClickLogin login_service:
        """
        self.url = url
        self.login = login_service
        self.session = utils.requests_retry_session()
        self.gh_id = None
        self.gh_nickname = None
        self.token = None
        self.index_url = None
        self.index_response = None
        self.violation_list = []


    def log_line(self, msg, gh_nickname=None, gh_id=None):
        line = '[{}]({}) {}'.format(gh_nickname if gh_nickname else self.gh_nickname,
                                    gh_id if gh_id else self.gh_id, msg)
        print(line)
        return line

    def log_err(self, err, logtype='log', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)

    def debug_log(self, err, logtype='debug', gh_nickname=None, gh_id=None):
        utils.log_error(self.log_line(err, gh_nickname, gh_id), logtype)
        print(err)

    def detect_account_type(self):
        m = re.search(r'>((订阅|服务)号)</a>', self.index_response, re.MULTILINE)
        if m:
            return m.group(1)

    def enter(self, gh_id, gh_nickname, pwd):

        scan = Scan(self.session)
        self.token = scan.get_session_with_cookie(gh_id, pwd)
        try:
            info = {"nickname": gh_nickname,
                    "gh_id": gh_id,
                    "pwd": ''
                    }
            with utils.open_write_data_file(gh_id, 'basic.json', utils.get_yesterday()) as f:
                json.dump(info, f)
        except:
            pass
        try:
            response = self.session.get(url=self.url, verify = False)
            self.index_url = str(response.url)
            try:
                token = re.findall('token=(\\d+)', self.index_url)[0]
            except IndexError:
                self.log_err('微信后台登录失败，检查Cookie是否有效',
                             gh_nickname=gh_nickname, gh_id=gh_id)
                return False
            self.gh_id = gh_id
            self.gh_nickname = gh_nickname
            self.token = token
            self.index_response = response.content.decode('utf-8')
            self.log_line('后台登录成功，Token={}'.format(token))
            return True
        except Exception as e:
            print(e)
            return False

    def save_data(self, data_file, data_date, data):
        with utils.open_write_data_file(self.gh_id, data_file, data_date) as f:
            json.dump(data, f)

    def detect_or_save(self, data_file, data_name, data_date, func, skip_exist=True, verbose=True):
        if skip_exist and utils.has_data_file(self.gh_id, data_file, data_date):
            if verbose:
                self.log_line('已存在{}，跳过'.format(data_name))
        else:
            if verbose:
                self.log_line('开始获取{}'.format(data_name))
            data = func(data_date)
            if data:
                if verbose:
                    self.log_line('获取{}成功'.format(data_name))
                self.save_data(data_file, data_date, data)
            else:
                self.log_err('获取{}失败,请重试,或单独爬取'.format(data_name))

    def save_basic_info(self, account, date):
        self.save_data('basic.json', date, account)

    def save_visitors(self, date):
        yest_visitor = new_visitors = Share_number = ""
        riqi = str(datetime.datetime.strptime(date, '%Y-%m-%d') - datetime.timedelta(days=1))[:10]
        resp = self.session.get(
            '{0}/wxopen/appdatacount?token={1}&lang=zh_CN&f=json&ajax=1&random={2}&action=overview_compare&id=7'
            '&default_start_time={3}&default_end_time={4}'.format(
                self.url, self.token, random.random(),
                int(time.mktime(time.strptime(str(riqi), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d')))), headers=header
        )
        try:
            date_time = str(date).replace('-','')
            data = resp.json()
            if data["base_resp"]["ret"] == 0:
                info = eval(data["default_time_data"])
                for y in range(len(info["list"])):
                    if info["list"][y]["ref_date"] == date_time:
                        yest_visitor = info["list"][y]["value"]
        except (KeyError, ValueError, TypeError, AttributeError, IndexError):
            self.debug_log(resp.content)
        result = self.session.get(
            "{0}/wxopen/appdatacount?token={1}&lang=zh_CN&f=json&ajax=1&random={2}&action=overview_compare&id=8"
            "&default_start_time={3}&default_end_time={4}".format(
                self.url, self.token, random.random(),
                int(time.mktime(time.strptime(str(riqi), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d')))), headers=header
        )
        try:
            date_time = str(date).replace('-','')
            datadata = result.json()
            if datadata["base_resp"]["ret"] == 0:
                info = eval(datadata["default_time_data"])
                for y in range(len(info["list"])):
                    if info["list"][y]["ref_date"] == date_time:
                        new_visitors = info["list"][y]["value"]
        except (KeyError, ValueError, TypeError, AttributeError, IndexError):
            self.debug_log(result.content)
        rest = self.session.get(
            '{0}/wxopen/appdatacount?token={1}&lang=zh_CN&f=json&ajax=1&random={2}&action=overview_compare&id=10'
            '&default_start_time={3}&default_end_time={4}'.format(
                self.url, self.token, random.random(),
                int(time.mktime(time.strptime(str(riqi), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d')))), headers=header
        )
        try:
            date_time = str(date).replace('-','')
            datainfo = rest.json()
            if datainfo["base_resp"]["ret"] == 0:
                info = eval(datainfo["default_time_data"])
                for y in range(len(info["list"])):
                    if info["list"][y]["ref_date"] == date_time:
                        Share_number = info["list"][y]["value"]
        except (KeyError, ValueError, TypeError, AttributeError, IndexError):
            self.debug_log(rest.content)
        return {"yest_visitor": yest_visitor, "new_visitors": new_visitors, "Share_number": Share_number}


    def save_Visitors_yesterday(self, date):
        visitors = ""
        date_time = str(date).replace('-','')
        resp = self.session.get(
            '{0}/wxopen/appdatacount?token={1}&lang=zh_CN&f=json&ajax=1&random={2}&action=overview_compare&id=4'
            '&default_start_time={3}&default_end_time={4}'.format(
                self.url, self.token, random.random(), int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))) + 86399), headers=header
        )
        try:
            result = resp.json()
            if result["base_resp"]["ret"] == 0:
                info = eval(result["default_time_data"])
                for y in range(len(info["list"])):
                    if info["list"][y]["ref_date"] == str(date_time):
                        visitors = info["list"][y]["value"]
        except (KeyError, ValueError, TypeError, IndexError):
            self.debug_log(resp.content)
        return {"visitors": visitors}

    def save_New_retained(self, date):
        new_retain = ""
        riqi = str(datetime.datetime.strptime(date, '%Y-%m-%d') - datetime.timedelta(days=1))[:10]
        date_time = riqi.replace('-','')
        resp = self.session.get(
            '{0}/wxopen/visitanalysis?token={1}&lang=zh_CN&f=json&ajax=1&random={2}&action=get_visit_retain'
            '&begin_timestamp={3}&end_timestamp={4}&offset=0&retain_type=1&grain_size=0&count=10'.format(
                self.url, self.token, random.random(), int(time.mktime(
                                           time.strptime(str(riqi),'%Y-%m-%d'))),
                int(time.mktime(time.strptime(str(riqi), '%Y-%m-%d'))) + 86399), headers=header
        )
        try:
            data = resp.json()
            if data["base_resp"]["ret"] == 0:
                info = eval(data["data_info"])
                for y in range(len(info["list"])):
                    if info["list"][y]["refdate"] == str(date_time):
                        new_retain = round(info["list"][y]["item"][0]["percentage"] / info["list"][y]["assign_user"] * 100, 2)
        except (KeyError, ValueError, TypeError, IndexError):
            self.debug_log(resp.content)
        return {"new_retain": new_retain}

    def save_publish_info(self, date):
        Exposure = click = income = ""
        for i in range(0,10):
            resp = self.session.get(
                '{0}/wxopen/weapp_publisher_stat?action=stat&page=1&page_size=90&start={1}&end={2}&pos_type=5'
                '&token={3}&appid=&spid=&_={4}'.format(
                    self.url, int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))),
                    int(time.mktime(time.strptime(str(date), '%Y-%m-%d'))), self.token,
                    int(round(time.time()) * 1000)), headers=header
            )
            try:
                data = resp.json()
                if data["base_resp"]["ret"] == 0:
                    if len(data["cost_list"]["cost"]) == 0:
                        Exposure = 0
                        click = 0
                        income = 0.00
                        continue
                    else:
                        Exposure = data["cost_list"]["cost"][0]["view_count"]
                        click = data["cost_list"]["cost"][0]["click_count"]
                        income = data["cost_list"]["cost"][0]["cost"] / 100
                        break
            except (KeyError, ValueError, TypeError, IndexError):
                self.debug_log(resp.content)
        return {"Exposure": Exposure, "click": click, "income": income}


def collect(login_service, account, data_date=None):
    if not data_date:
        data_date = utils.get_yesterday()
    srv = WeChatClient(login_service)
    if not srv.enter(account['gh_id'], account['nickname'], account['pwd']):
        return
    srv.save_basic_info(account, data_date)
    srv.detect_or_save('app-msg-visitors-info.json','访问人数信息', data_date,
                       srv.save_visitors)
    srv.detect_or_save('app-msg-visitors-data.json','累计信息', data_date,
                       srv.save_Visitors_yesterday)
    srv.detect_or_save('app-New-retained.json','新增留存', data_date,
                       srv.save_New_retained)
    srv.detect_or_save('app-publish-info.json','流量主数据', data_date,
                       srv.save_publish_info)

def test_collect(date):
    library = utils.default_library()
    account_list = library.get_account_list()
    if account_list:
        for gh_id in account_list:
            account = library.get_account_data(gh_id)
            collect(None, account, date)
    else:
        print('账号列表为空，退出')